package ru.zombator.taskman.client.ui.dialogs;

import java.io.IOException;
import java.rmi.RemoteException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.layout.GridData;

import ru.zombator.taskman.client.ui.ClientWindow;
import ru.zombator.taskman.client.ui.images.ImageNames;
import ru.zombator.taskman.client.ui.images.Registry;
import ru.zombator.taskman.client.ui.utils.UiUtils;
import ru.zombator.taskman.core.domain.ITaskProject;
import ru.zombator.taskman.core.query.IClient;
import ru.zombator.taskman.core.query.ITypedPacket;
import ru.zombator.taskman.core.query.TypedPacket;
import ru.zombator.taskman.core.query.payload.ErrorResponse;
import ru.zombator.taskman.core.query.payload.ObjectsListedResponse;
import ru.zombator.taskman.core.query.payload.ProjectListRequest;
import ru.zombator.taskman.core.query.payload.ProjectListRequest.ShowProjects;

import org.eclipse.swt.widgets.Combo;

/**
 * Диалог создания нового проекта
 * 
 * @author nvamelichev
 * 
 */
public class JoinProjectDialog extends TitleAreaDialog {
    private Combo projectName;
    private Text projectPassword;
    
    private UUID id = null;
    private String name = "";
    private String password = "";
    
    private boolean isValid = true;
    private String errorMessage;
    
    private static final String DEFAULT_MESSAGE = "Выберите проект, к которому вы хотите присоединиться";
    
    private ClientWindow mainWnd;
    
    private void validateAndRememberValues() {
        validateDialog();
        name = projectName.getText();
        id = (UUID) projectName.getData(Integer.toString(projectName.getSelectionIndex()));
        password = projectPassword.getText();
    }
    
    private final ModifyListener VALIDATION_LISTENER = new ModifyListener() {
        @Override
        public void modifyText(ModifyEvent e) {
            validateAndRememberValues();
        }
    };
    
    private final SelectionAdapter SELECTION_LISTENER = new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            validateAndRememberValues();
        }
    };    
    
    private void validateDialog() {
        boolean oldIsValid = isValid;
        String newErrorMessage = "";
        
        isValid = true;
        if (projectName.getData(Integer.toString(projectName.getSelectionIndex())) == null) {
            isValid = false;
            newErrorMessage = "Выберите проект";
        } else if (projectPassword.getText().length() == 0) {
            isValid = false;
            newErrorMessage = "Введите пароль проекта";
        }
        
        if (oldIsValid != isValid || !newErrorMessage.equals(errorMessage)) {
            if (!isValid) {
                setMessage(newErrorMessage, IMessageProvider.ERROR);
            } else {
                setMessage(DEFAULT_MESSAGE);
            }
        }
        oldIsValid = isValid;
        errorMessage = newErrorMessage;
        
        Button okButton = getButton(IDialogConstants.OK_ID);
        if (okButton != null)
            okButton.setEnabled(isValid);
    }
    
    public UUID getId() {
        return this.id;
    }
    
    public String getPassword() {
        return this.password;
    }
    
    public JoinProjectDialog(Shell parentShell, ClientWindow mainWnd) {
        super(parentShell);
        this.mainWnd = mainWnd;
    }
    
    private void populateProjectList() {
        IClient client = mainWnd.getClient();
        projectName.add("");
        projectName.setData("0", null);
        projectName.select(0);
        try {
            ITypedPacket response = client.sendPacket(new TypedPacket(new ProjectListRequest(ShowProjects.NON_JOINED)));
            Object responseObject = response.asObject();
            if (responseObject instanceof ErrorResponse) {
                throw new RemoteException( ((ErrorResponse)responseObject).getMessage() );
            } else {
                ObjectsListedResponse olr = (ObjectsListedResponse) responseObject;
                @SuppressWarnings("unchecked")
                List<ITaskProject> notJoinedProjects = (List<ITaskProject>) olr.getObjects();
                int index = 1;
                for (ITaskProject proj: notJoinedProjects) {
                    projectName.add(proj.getName());
                    projectName.setData(Integer.toString(index), proj.getId());
                    index++;
                }
                return;
            }
        } catch (RemoteException e) {
            UiUtils.showError(String.format("Произошла ошибка при получении списка проектов:\n%s",
                    e.getMessage()));
        } catch (TimeoutException e) {
            UiUtils.showError("Время ожидания истекло при получении списка проектов.");            
        } catch (IOException e) {
            UiUtils.showError("Произошла ошибка при попытке связаться с сервером.");            
        }
        close();
    }
    
    @Override
    public void create() {
        super.create();
        
        setTitle("Присоединиться к проекту");
        setMessage(DEFAULT_MESSAGE);
        getShell().setText("Присоединиться к проекту");
        
        populateProjectList();
        validateDialog();
    }
    
    @Override
    protected Control createDialogArea(Composite parent) {
        Composite z = (Composite) super.createDialogArea(parent);
        z.setLayout(new GridLayout(1, false));
        
        Composite area = new Composite(z, SWT.NONE);
        area.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
        GridLayout gl_area = new GridLayout(2, false);
        area.setLayout(gl_area);
        
        Label label = new Label(area, SWT.NONE);
        label.setText("Проект:");
        
        projectName = new Combo(area, SWT.READ_ONLY);
        projectName.setTextLimit(50);
        projectName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
        projectName.addSelectionListener(SELECTION_LISTENER);
        
        Label label_1 = new Label(area, SWT.NONE);
        label_1.setText("Пароль:");
        
        projectPassword = new Text(area, SWT.BORDER | SWT.PASSWORD);
        projectPassword.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
        projectPassword.addModifyListener(VALIDATION_LISTENER);
        
        setTitleImage(Registry.getImage(ImageNames.JOIN_PROJECT));
        
        return area;
    }

    public String getName() {
        return name;
    }
}
